<?php
/**
 * Cache implementation
 *
 * @author Martin "DevelX" Jurča
 * @version 2010-08-10
 */
class Cache {
    const DB = 1;
    const IMG = 2;
    const OUTPUT = 4;
    const ALL = 7;
    private static $dbfiles = -1;
    private static $imgfiles = -1;
    private static $outputfiles = -1;
    private static $outputfile = null;
    private static $outputdetails = array();
    private static $lastPausedOutput = null;

    public static function flushTable($name) {
        $len = strlen(Config::ROOT);
        $records = glob(Config::ROOT . "/cache/db/$name.*");
        if (is_array($records)) {
            foreach ($records as $record) {
                FTP::deleteFile(substr($record, $len));
            }
        }
    }

    public static function &dbQuery($table, $query) {
        $file = Config::ROOT . "/cache/db/$table." . sha1($query);
        if (is_file($file) && is_readable($file) &&
                ((Config::CACHE_DB_TIMEOUT == -1) ||
                (time() - filectime($file) < Config::CACHE_DB_TIMEOUT))) {
            $data = file_get_contents($file);
            $data = unserialize($data);
            return $data;
        }
        $result = false;
        return $result;
    }

    public static function dbSaveQuery($table, $query, &$result) {
        if (Config::MAX_CACHE_SIZE == 0) {
            return;
        }
        $file = "/cache/db/$table." . sha1($query);
        if (!file_exists(Config::ROOT . $file)) {
            FTP::createFile($file);
        }
        $handle = @fopen(Config::ROOT . $file, 'wb');
        if (!is_resource($handle)) {
            return;
        }
        flock($handle, LOCK_EX);
        $data = serialize($result);
        fwrite($handle, $data);
        flock($handle, LOCK_UN);
        fclose($handle);
    }

    public static function startOutputCache($id, $renderOptions = array()) {
        $hash = sha1(serialize($renderOptions));
        $file = Config::ROOT . "/cache/output/$id" . $hash;
        if (is_readable($file) && ((Config::CACHE_OUTPUT_TIMEOUT == -1) ||
                (time() - filectime($file) < Config::CACHE_OUTPUT_TIMEOUT))) {
            echo file_get_contents($file);
            return true;
        }
        if (!file_exists($file)) {
            FTP::createFile("/cache/output/$id" . $hash, 0666);
        }
        self::$outputfile = @fopen($file, 'wb');
        if (!is_resource(self::$outputfile)) {
            return false;
        }
        self::$outputdetails[$id] = $hash;
        flock(self::$outputfile, LOCK_EX);
        ob_start();
        return false;
    }

    public static function pauseOutputCache($id) {
        $data = ob_get_flush();
        if ($data === false) {
            return false;
        }
        echo $data;
        if (!is_resource(self::$outputfile)) {
            return false;
        }
        $data = @fwrite(self::$outputfile, $data);
        if ($data === false) {
            return false;
        }
        flock(self::$outputfile, LOCK_UN);
        fclose(self::$outputfile);
        self::$lastPausedOutput = $id;
        return true;
    }

    public static function continueOutputCache($id) {
        self::$lastPausedOutput = null;
        if (!isset(self::$outputdetails[$id])) {
            return false;
        }
        $file = Config::ROOT . "/cache/output/$id" .
                self::$outputdetails[$id];
        self::$outputfile = @fopen($file, 'ab');
        if (!is_resource(self::$outputfile)) {
            return false;
        }
        flock(self::$outputfile, LOCK_EX);
        return ob_start();
    }

    public static function endOutputCache($id) {
        $data = ob_get_clean();
        if ($data === false) {
            return false;
        }
        echo $data;
        $data = @fwrite(self::$outputfile, $data);
        if ($data === false) {
            return false;
        }
        flock(self::$outputfile, LOCK_UN);
        fclose(self::$outputfile);
        unset(self::$outputdetails[$id]);
        return true;
    }

    public static function useModuleDisplayer($moduleName, &$parameters) {
        Modules::getModule($moduleName)->display($parameters);
        return true;
    }

    public static function flushModulePages($moduleName) {
        $len = strlen(Config::ROOT);
        $files = glob(Config::ROOT . "/cache/output/$moduleName-*");
        foreach ($files as $file) {
            FTP::deleteFile(substr($file, $len));
        }
    }

    public static function &getImage(&$parameters) {
        $hash = sha1(serialize($parameters));
        $file = Config::ROOT . "/cache/img/$hash.jpg";
        if (is_readable($file) && ((Config::CACHE_IMAGE_TIMEOUT == -1) ||
                (time() - filectime($file) < Config::CACHE_IMAGE_TIMEOUT))) {
            $data = file_get_contents($file);
            return $data;
        }
        if (Config::MAX_CACHE_SIZE == 0) {
            return Image::render($parameters, false);
        }
        FTP::createFile("/cache/img/$hash.jpg");
        Image::render($parameters, $file);
        $file = file_get_contents($file);
        return $file;
    }

    public static function flushCache($which) {
        if ($which | self::DB > 0) {
            self::flushCacheType('db');
        }
        if ($which | self::OUTPUT > 0) {
            self::flushCacheType('output');
        }
        if ($which | self::IMG > 0) {
            self::flushCacheType('img');
        }
    }

    private static function flushCacheType($which) {
        $files = glob(Config::ROOT . "/cache/$which/*");
        $len = strlen(Config::ROOT);
        foreach ($files as $file) {
            FTP::deleteFile(substr($file, $len));
        }
    }
}
?>
